from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View
import json
from django.core.serializers import serialize
from myapp.myser import UserSer,PicsSer
from rest_framework.response import Response
from rest_framework.views import APIView
from myapp.myser import *
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

from myapp.models import User,Pics,Goods
import requests
import jwt_test

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from .models import *
import redis

# 定义ip地址和端口
host = '127.0.0.1'
port = 6379

# 定义链接对象
r = redis.Redis(host=host, port=port)

import pymongo

# 建立mongo的链接对象
mongo_client = pymongo.MongoClient(host='localhost',port=27017)

#商品检索接口
class GoodsSearch(APIView):

	def get(self,request):


		#接收参数
		word = request.GET.get("word",None)

		#检索  模糊匹配 管道 代表 or 并且 &
		#翻译sql select * from goods where (name like '%word%' or desc like '%word%') and (parms like '%word%')
		goodslist = Goods.objects.filter(Q(name__icontains=word) | Q(desc__icontains=word) )

		#序列化
		goods_ser = GoodsSer(goodslist,many=True)

		return Response(goods_ser.data)


#工具方法，获取前n名的数据
def get_top_n(num):

	#获取redis数据
	goods_click = r.zrange('good_rank',0,-1,desc=True,withscores=True)[:num]
	#获取mysql数据
	goods = Goods.objects.in_bulk([int(item[0]) for item in goods_click])

	#合并操作
	res = []
	for item in goods_click:

		#遍历列表
		#捕获异常，防止mysql和redis数据不同步问题
		try:
			res.append({int(item[1]):goods[int(item[0])]})
		except Exception as e:
			pass

	print(res)

	return res


#商品排行榜数据视图
class GoodRank(APIView):

	def get(self,request):

		#获取排名前n的数据
		get_res = get_top_n(10)

		res = []
		#遍历进行序列化
		for dic in get_res:
			for k,v in dic.items():
				#序列化
				data = GoodsSer(v).data
				#将商品点击数附加到商品序列化数据中
				data['clicks'] = k
				res.append(data)

		#返回
		return Response({
            'data':res
        })





# 新的商品参与排名
class GoodsClick(APIView):

	def get(self,request):

		#接收参数
		id = request.GET.get("id",None)

		#修改商品的点击数
		r.zincrby("good_rank",1,int(id))

		get_top_n(10)

		return Response({"message":"访问加1"})



# 对结果集美化方法
def dictfetchall(cursor):

    # 获取游标描述
    desc = cursor.description

    return [
        dict(zip( [col[0] for col in desc],row))

        for row in cursor.fetchall()
    ]




# 商品关注接口（查询用户关注过的商品列表）
class UidFlow(View):
    def get(self,request):

        uid = request.GET.get("uid",None)

        # 建立游标对象
        cursor = connection.cursor()

        # 执行sql语句
        cursor.execute('select a.id, a.name,a.create_time from goods a left join userflow b on a.id = b.gid where b.uid = %s' % str(uid))

        # 获取结果
        # result = cursor.fetchall()
        result = dictfetchall(cursor)

        # 返回结果 手动序列化
        # 序列化需要注意出现中文，防止乱码
        return HttpResponse(json.dumps(result,ensure_ascii=False,indent=4,default=str),content_type='application/json')


# 关注商品接口(取消）
class GetFlow(APIView):

    def get(self,request):
        id = request.GET.get('id',None)
        uid = request.GET.get('uid',None)
        type = request.GET.get('type',1)


        # 限制用户刷屏操作
        redis_flow = r.get(uid)
        if redis_flow:
            return Response({
                'code':400,
                'message': '请稍后操作'
            })



        if int(type)==1:
            # 关注
            userflow = UserFlow(gid=int(id),uid=int(uid))
            try:
                userflow.save()
                message = '关注成功'
                goods = Goods.objects.filter(id=int(id)).first()
                goods.flow = goods.flow + 1
                goods.save()
                # redis保存当前用户操作
                r.set(uid, '28')
                # 设置时间为180秒
                r.expire(uid, 180)
            except Exception as e:
                print(str(e))
                message = '不能重复关注'
                pass
        elif int(type) == 0:
                # 取关
                UserFlow.objects.filter(gid=int(id),uid=int(uid)).delete()
                message = '取关成功'
                goods = Goods.objects.filter(id=int(id)).first()
                goods.flow = goods.flow - 1
                goods.save()
                # redis保存当前用户操作
                r.set(uid, '28')
                # 设置时间为180秒
                r.expire(uid, 180)

        else:
            # 批量取关
            ids = request.GET.get("ids", None)
            # 批量操作
            UserFlow.objects.filter(uid=int(uid)).delete()
            # 强转
            id_list = eval(ids)

            for id in id_list:
                userflow = UserFlow(gid=int(id), uid=int(uid))
                userflow.save()
                # redis保存当前用户操作
                r.set(uid, '28')
                # 设置时间为180秒
                r.expire(uid, 180)

            message = "批量关注成功"

        return Response({'message':message})




# 用户列表
class UserList(APIView):
    def get(self,request):

        # 查询
        user = User.objects.filter()
        # 序列化
        user_ser = UserSer(user,many=True)

        return Response(user_ser.data)






# 评论列表
class CommentList(APIView):
    def get(self,request):

        # 当前页
        page = int(request.GET.get('page',1))
        # 一页有多少条数据
        size = int(request.GET.get('size',1))

        # 商品id
        id = request.GET.get('id',None)

        # 从哪里开始切片
        data_start = (page-1) * size
        #定义切到哪里
        data_end = page * size


        # 查询评论数据
        comment = Comment.objects.filter(gid=id)[data_start:data_end]

        #查询总数量
        count = Comment.objects.filter(gid=id).count()

        # 序列化
        comment_ser = CommentSer(comment,many=True)

        return Response({
            'commentlist': comment_ser.data,
            'total':count
        })



# 反序列化入库（商品评论）
class InsertComment(APIView):
    def post(self,request):

        print(request.data)

        uid = request.POST.get("uid",None)


        if r.get(str(uid)):

            return Response({

                'code':400,
                'message':'您评论过快，请稍候'

            })



        # 初始化参数
        comment = CommentSer(data=request.data)
        # 数据校验
        if comment.is_valid():
            # 数据入库
            # comment.create(comment.data)
            comment.save()


            # 插入评论标记
            r.set(str(uid),"123")
            r.expire(str(uid),30)

        return Response({
            'code':200,
            'message':'评论成功'
        })






#统计在线人数
class GetOnLine(APIView):
	def get(self,request):
		#获取客户ip
		if 'HTTP_X_FORWARDED_FOR' in request.META:
			ip = request.META.get('HTTP_X_FORWARDED_FOR')
		else:
			ip = request.META.get('REMOTE_ADDR')
		#对用户ip进行存储
		r.sadd("online",ip)
		#设置超时时间 超时时常单位秒
		r.expire("online",20)
		#获取在线人数的数量
		myset = r.smembers('online')
		#返回数据
		return Response({'online':len(myset)})



#修改标签
class UpdateTags(APIView):
    def get(self, request):
        id = request.GET.get('id', None)
        tags = request.GET.get('tags', None)
        tags = tags.split(',')
        db = mongo_client.md
        table = db.mytag
        # 修改mongo数据
        table.update({'gid':str(id)},{"$set":{'tags':tags}})
        return Response({
            'code': 200,
            'message': '标签修改成功'
        })






# 修改商品标签
class UpdateGoods(APIView):
    def get(self, request):
        id = request.GET.get('id','null')
        name = request.GET.get('name','null')
        desc = request.GET.get('desc','null')
        parms = request.GET.get('parms','null')
        price = request.GET.get('price','null')
        cate_id = request.GET.get('cate_id','null')


        # 查询
        goods = Goods.objects.filter(id=int(id)).first()

        # 修改数据库中的商品数据
        goods.name=name
        goods.desc=desc
        goods.parms=parms
        goods.price=price
        goods.cate_id=cate_id
        goods.save()

        res = {}
        res['code'] = 200,
        res['id'] = goods.id
        res['message'] = '修改成功'

        return Response(res)




# 导入bson
from bson import json_util as jsonb
class GetTags(View):

    def get(self,request):

        id = request.GET.get('id',None)

        # 建立数据库对象
        db = mongo_client.md
        # 建立表对象
        table = db.mytag

        # 查询数据
        res = table.find_one({'gid':str(id)})

        # ensure_ascii=False 防止中文乱码
        return HttpResponse(jsonb.dumps(res,ensure_ascii=False))



# mongo库操作
# 商品标签添加接口
class InsertTags(APIView):

    def get(self,request):
        id = request.GET.get('id',None)
        tags = request.GET.get('tags',None)
        tags = tags.split(",")



        # 建立数据库对象
        db = mongo_client.md
        # 建立表对象
        table = db.mytag

        # 排重操作
        # 查询
        res = table.find({'gid':str(id)}).count()

        if res>0:
            return Response({'message':'重复数据'})
        else:
            # 入库操作
            table.insert({'gid':str(id),"tags":tags})


            return Response({'message':'入库成功'})


# 商品信息接口
class GoodInfo(APIView):
    def get(self,request):

        id = int(request.GET.get("id",0))

        # 查询数据
        good = Goods.objects.get(id=id)

        # 序列化操作
        goods_ser = GoodsSer(good)

        print(goods_ser)

        return Response(goods_ser.data)




# 获取单个商品
class GoodsAll(APIView):

    def get(self, request):
        id = int(request.GET.get('id', 1))

        if id:
            # 查询数据
            goodsitem = Goods.objects.filter(id=id).first()

            # 序列化
            goodsitem_ser = GoodsSer(goodsitem)

            return Response({
                'data': goodsitem_ser.data
            })

        return Response({
            'data': '获取失败'
        })




# 商品列表页
class GoodsList(APIView):
    def get(self,request):

        # 当前页
        page = int(request.GET.get('page',1))
        # 一页有多少条商品
        size = int(request.GET.get('size',1))

        # 定义从哪开始切
        data_start = (page-1) * size

        # 定义切到哪
        data_end = page * size

        # 查询数据
        goodslist = Goods.objects.all()[data_start:data_end]

        # 查询总数量
        count = Goods.objects.count()

        # 序列化操作
        goods_ser = GoodsSer(goodslist,many=True)

        res = {}
        res['total'] = count
        res['data'] = goods_ser.data
        return Response(res)









# 幻灯片接口
class PicsList(APIView):

    def get(self, request):
        # 查询数据
        pics = Pics.objects.filter().values('title', 'link', 'img')

        # 序列化对象
        pics_ser = PicsSer(pics, many=True)

        return Response(pics_ser.data)

# 插入幻灯片
class Insertgoods(APIView):
    def get(self, request):
        name = request.GET.get('name', 'null')
        desc = request.GET.get('desc', 'null')
        parms = request.GET.get('parms', 'null')
        cate_id = request.GET.get('cate_id', 'null')
        price = request.GET.get('price', 'null')

        # 排重
        goods = Goods.objects.filter(name=name).first()

        if goods:
            res = {}
            res['code'] = 405
            res['message'] = '该商品已存在'
            return Response(res)


        r.set('parms', parms)
        # 入库操作
        goods = Goods(name=name, desc=desc, cate_id=cate_id, price=price, parms=parms)
        goods.save()


        # 查询商品id
        goods = Goods.objects.filter(name=name).first()

        res = {}
        res['code'] = 200
        res['message'] = '商品添加成功'
        res['id'] = goods.id
        return Response(res)







